/* 
 * File:   Float.cpp
 * Author: mariano
 *
 * Created on December 20, 2009, 11:38 AM
 */

#include <stdlib.h>
#include "float.h"
#include <iostream>
#include <cassert>
#include <sstream>
#include <unistd.h>

#define RUNTEST(t,d) { t(); cerr << "OK : " << #d  << endl; }
using namespace std;

void testMemoria() {
    Float f, g;
    g = Float(f);
    f = Float(2);
    assert(g != f );
    f = Float("0");
    assert(g == f);
    f = Float("-0");
    assert(g == f);
    f = Float("0.0");
    assert(g == f);
    f = Float("0,0");
    assert(g == f);
}

void testComparadores() {
    Float f,g;
    assert(f == g);
    assert(!(f!=g));
    assert(!(f<g));
    assert(!(f>g));
    assert(f>=g);
    assert(f<=g);

    f = Float(123);
    g = Float(-123);
    assert( (f != g));
    assert(!(f == g));
    assert(!(f <  g));
    assert( (f >  g));
    assert( (f >= g));
    assert(!(f <= g));

    f = Float(1.0001);
    g = Float(1.00001);
    assert( (f != g));
    assert(!(f == g));
    assert(!(f <  g));
    assert( (f >  g));
    assert( (f >= g));
    assert(!(f <= g));

    f = Float("0.00001");
    g = Float();
    assert( (f != g));
    assert(!(f == g));
    assert(!(f <  g));
    assert( (f >  g));
    assert( (f >= g));
    assert(!(f <= g));
}

void testOperadores() {
    Float a, b, result;
    a = Float(1);
    b = Float(1);
    result =Float(2);
    assert(a+b == result);
    a+=b;
    assert(a+b == result+b);
    assert(a*b==a);
    assert(a*result == Float(4));
    assert(a-b == b);
    a = Float() - a;
    assert(a + b == Float() - b);
    assert(a*b == a);
    b = Float() - b;
    assert(b*b == Float() - b);
    assert(Float() + Float() == Float());
    assert(Float("-1")*Float() == Float());
    assert(Float("-0.5") - Float("-0.5") == Float());
    assert(Float().similar(Float()));
    assert(Float("0.000000000001").similar(Float()));
    a = Float("-0.2");
    a *= a;
    assert(a.similar(Float("0.04")));
    a = Float("-0.2");
    a *= Float("1");
    assert(a.similar(Float("-0.2")));
}

void testStressing() {

    Float a, b , c, acum;
    a = Float();
    b = Float(1);
    c = Float(1);
    acum = Float();
    double fa, fb, fc, facum = 0;
    fa = 0;
    fb = 1;
    fc = 1;
    for(int i = 0; i < 20; i++) {
        Float temp = c;
        c = a + b;
        a = b;
        b = temp;
        double ftemp = fc;
        fc = fa + fb;
        fa = fb;
        fb = ftemp;
        assert(c == Float(c));
        acum += c;
        facum += fc;
        assert(acum == Float(facum));
    }
    acum = Float();
    a = Float(1);
    b = Float("-0.2");
    c = Float("1");
    facum = 0.0;
    fa = 1;
    fb = -0.2;
    fc = 1;
    for(int i = 0; i < 6; i++){
        acum += (a * c);
        c *= b;
        facum += (fa*fc);
        fc *=fb;
        assert(c.similar(Float(fc)));
        assert(acum.similar(Float(facum)));
    }
    
}

void testFloat(){
    Float::setLimit(15);
    cout << endl << "FLOAT TESTS" << endl;
    RUNTEST(testMemoria, constructores y copias)
    RUNTEST(testComparadores, comparadores)
    RUNTEST(testOperadores, suma resta y multiplicacion)
    RUNTEST(testStressing, test de stressing)
}

void testParser(){
	string a,b;
	cout << "*** Prueba parser ***" << endl;
	a = "93,25";
	while(a!="quit" && a!="q"){
		Float fa(a);
		cout << "para el numero: " << a << " ,su float es: " << fa<< endl;
		cout << "inserte a en el formato numero,numero: ";
		cin >> a;
	}
}

void testComparacion(){
	string a,b;
	a = "93,25";
	b = "23,5";
	cout << " *** Prueba de operadores de comparacion ***"<< endl;
	while(a!="quit" && a!="q"){

		Float fa(a);
		Float fb(b);
		string res;
		res = ((fa==fb)?"true":"false");
		cout << a << " == " << b<< " == " << res << '\t';
		res = ((fa!=fb)?"true":"false");
		cout << a << " != " << b<< " == " << res << endl;
		res = ((fa>=fb)?"true":"false");
		cout << a << " >= " << b<< " == " << res << '\t';
		res = ((fa<fb)?"true":"false");
		cout << a << " < " << b<< " == " << res << endl;
		res = ((fa<=fb)?"true":"false");
		cout << a << " <= " << b<< " == " << res << '\t';
		res = ((fa>fb)?"true":"false");
		cout << a << " > " << b<< " == " << res << endl;
		cout << "inserte a: ";
		cin >> a;
		if(a != "q" && a!= "quit"){
			cout << "inserte b: ";
			cin >> b;
		}
	}
}

void testSuma(){
	string a,b;
	cout << "*** Prueba de la suma (y resta) ***" << endl;
	a = "1,0";
	b = "2,0";
	while(a!="quit" && a!="q"){
		Float fa(a);
		Float fb(b);
		cout << fa << " + " << fb << " == ";
		fa += fb;
		cout << fa << endl;
		cout << "inserte a: ";
		cin >> a;
		if(a != "q" && a!= "quit"){
			cout << "inserte b: ";
			cin >> b;
		}
	}
}

void testMultip(){
	string a,b;
	cout << "*** Prueba de la multiplicacion ***" << endl;
	a = "1,0";
	b = "2,0";
	while(a!="quit" && a!="q"){
		Float fa(a);
		Float fb(b);
		cout << fa << " * " << fb << " == ";
		fa *= fb;
		cout << fa << endl;
		cout << "inserte a: ";
		cin >> a;
		if(a != "q" && a!= "quit"){
			cout << "inserte b: ";
			cin >> b;
		}
	}
}

void testShift(){
	string a,b;
	cout << "*** Prueba shifteo (>>) ***" << endl;
	a = "2,0";
	int n = 2;
	while(a!="quit" && a!="q"){
		Float fa(a);
		cout << fa << " >> ";
		cout << n << " == ";
		fa >>= n;
		cout << fa << endl;
		cout << "inserte a: " ;
		cin >> a;
		if(a != "q" && a!= "quit"){
			cout << "inserte n: " ;
			cin >> n;
		}
	}
}

void mainFloat() {
	char opt;
	bool salir = false;
    string leyenda = "para salir del test ingrese \"q\" o \"quit\"";
	cout << endl << endl << "BIENVENIDO A LOS TESTS DE FLOAT"<<endl;
	cout << "Elija un test"<< endl << leyenda << endl;
	while(!salir){
		opt = 'a';
		cout << "Opciones:" << endl;
		cout << "++++++++++++++++++"<<endl;
		cout << "1.- Prueba parser " << endl;
		cout << "2.- Prueba de operadores de comparacion " << endl;
		cout << "3.- Prueba de la suma (y resta) " << endl;
		cout << "4.- Prueba de la multiplicacion " << endl;
		cout << "5.- Prueba shifteo (>>) " << endl;
		cout << "6.- Salir (q o quit)" << endl << endl;
		cout << "ingrese opcion: ";
        cin >> opt;
		cout << endl<<endl;
		     if(opt == '1'){cout << leyenda << endl;testParser();}
        else if(opt == '2'){cout << leyenda << endl;testComparacion();}
		else if(opt == '3'){cout << leyenda << endl;testSuma();}
		else if(opt == '4'){cout << leyenda << endl;testMultip();}
		else if(opt == '5'){cout << leyenda << endl;testShift();}
		else if(opt == '6'){salir = true;}
		else if(opt == 'q'){salir = true;}
		else{cout << "Opcion Incorrecta"<< endl;cout << leyenda << endl;}
    }

	cout << "*******************************" << endl;
}

